/*
 * Copyright (C) 2022 Huawei Technologies Co., Ltd.
 * Licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
#include "securec.h"
#include "tee_defines.h"
#include "tee_ext_api.h"
#include "tee_log.h"
#include "tee_dynamic_srv.h"
#include "tee_drv_client.h"
#include "se_main.h"
#include "se_service.h"

#define TEE_TASK_UNREGISTER_TA 0x1002
#define TEE_TASK_TA_CREATE     0x1009
#define TEE_TASK_TA_RELEASE    0x1010

static void se_fn(tee_service_ipc_msg *msg, uint32_t sndr, tee_service_ipc_msg_rsp *rsp)
{
    if (rsp == NULL)
        return;

    if (msg == NULL) {
        rsp->ret = TEE_ERROR_BAD_PARAMETERS;
        return;
    }

    TEE_UUID uuid;
    rsp->ret = tee_srv_get_uuid_by_sender(sndr, &uuid);
    if (rsp->ret != 0)
        return;

    uint32_t msg_vaddr = 0;
    uint32_t msg_size = msg->args_data.arg1;

    uint32_t rsp_vaddr = 0;
    uint32_t rsp_size = msg->args_data.arg4;
    int ret = tee_srv_map_from_task(sndr, (uint32_t)msg->args_data.arg0, msg_size, &msg_vaddr);
    ret |= tee_srv_map_from_task(sndr, (uint32_t)msg->args_data.arg3, rsp_size, &rsp_vaddr);
    if (ret != 0) {
        rsp->ret = TEE_ERROR_GENERIC;
        tee_srv_unmap_from_task(rsp_vaddr, rsp_size);
        tee_srv_unmap_from_task(msg_vaddr, msg_size);
        return;
    }
    rsp->ret = TEE_SUCCESS;

    se_service_cmd((struct se_srv_msg_t *)(uintptr_t)msg_vaddr, &uuid, sndr,
        (struct se_srv_rsp_t *)(uintptr_t)rsp_vaddr);

    tee_srv_unmap_from_task(rsp_vaddr, rsp_size);
    tee_srv_unmap_from_task(msg_vaddr, msg_size);
    return;
}

static void se_unregister(tee_service_ipc_msg *msg, uint32_t sndr, tee_service_ipc_msg_rsp *rsp)
{
    (void)sndr;
    (void)msg;
    (void)rsp;
    return;
}

static void se_ta_create(tee_service_ipc_msg *msg, uint32_t sndr, tee_service_ipc_msg_rsp *rsp)
{
    (void)sndr;
    (void)msg;
    (void)rsp;
    return;
}

static void se_ta_release(tee_service_ipc_msg *msg, uint32_t sndr, tee_service_ipc_msg_rsp *rsp)
{
    (void)sndr;
    (void)msg;
    (void)rsp;
    return;
}

enum srv_cmd {
    SRV_SE_IPC_CMD_0 = 0x0,
};

static struct srv_dispatch_t dispatch_fns[] = {
    { TEE_TASK_UNREGISTER_TA, se_unregister },
    { TEE_TASK_TA_CREATE, se_ta_create },
    { TEE_TASK_TA_RELEASE, se_ta_release },
    { SRV_SE_IPC_CMD_0, se_fn },
};

void tee_task_entry(void)
{
    se_service_info_init();

    tee_srv_cs_server_loop(SE_PATH, dispatch_fns, sizeof(dispatch_fns) / sizeof(dispatch_fns[0]), NULL);
}
